package com.battle.service.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.battle.pojo.entity.Resource;
import com.battle.pojo.entity.Role;
import com.battle.pojo.enums.resource.ResourceTypeEnum;
import com.battle.pojo.event.resource.CreateResourceEvent;
import com.battle.pojo.param.resource.*;
import com.battle.pojo.resource.MetaDto;
import com.battle.pojo.vo.resource.GetResourceTreeVo;
import com.battle.service.repository.in.ResourceRepository;
import com.battle.service.repository.in.RoleRepository;
import com.battle.service.service.in.ResourceService;
import nirvana.core.exceptions.BizException;
import nirvana.core.utils.ids.IdGenerator;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 【描 述】：资源服务
 * 【环 境】：J2SE 17
 * 【详 细】：
 *
 */
@Service
public class ResourceServiceImpl implements ResourceService {

    private final ResourceRepository resourceRepository;
    private final RoleRepository roleRepository;

    private final ApplicationEventPublisher publisher;

    public ResourceServiceImpl(ResourceRepository resourceRepository, RoleRepository roleRepository, ApplicationEventPublisher publisher) {
        this.resourceRepository = resourceRepository;
        this.roleRepository = roleRepository;
        this.publisher = publisher;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSystemResource(JSONArray param) {
        if (param == null) {
            throw new BizException("参数不能为空");
        }

        //删除旧的
        List<Resource> listByEntity = resourceRepository.getListByEntity(new Resource());
        if (CollectionUtil.isNotEmpty(listByEntity)){
            //提取ids
            List<Long> ids = listByEntity.stream().map(Resource::getId).distinct().collect(Collectors.toList());
            if (!resourceRepository.trueDeletionByIds(ids)){
                throw new BizException("资源推送失败");
            }
        }


        checkResource(param, new ArrayList<>());
        Resource resource = new Resource();
        resource.setId(IdGenerator.SNOW.generate());
        resource.setContent(param.toString());
        if (!resourceRepository.create(resource)){
            throw new BizException("资源推送失败");
        }
    }

    @Override
    public JSONArray getResourceTree(List<ResourceTypeEnum> typeList) {
        Resource systemResource = resourceRepository.getByEntity(new Resource());
        if (systemResource == null) {
            throw new BizException("资源不存在");
        }
        JSONArray jsonArray = new JSONArray(systemResource.getContent());
        filterResourceTree(jsonArray, null, typeList);
        return jsonArray;
    }

    @Override
    public JSONArray getUserResourceTreeByUserId(Long userId, List<ResourceTypeEnum> typeList) {
        Resource systemResource=resourceRepository.getByEntity(new Resource());
        List<Long> roleIdList = roleRepository.getRoleIdsListByUserId(userId);
        if (ArrayUtil.isEmpty(roleIdList)) {
            return new JSONArray();
        }
        JSONArray jsonArray = new JSONArray(systemResource.getContent());
        List<String> resourceCodeList = getCodeListByUserId(userId);
        filterResourceTree(jsonArray, resourceCodeList, typeList);
        return jsonArray;
    }

    @Override
    public JSONArray getUserResourceListByUserId(Long userId, List<ResourceTypeEnum> typeList) {
        JSONArray list = new JSONArray();
        Resource systemResource=resourceRepository.getByEntity(new Resource());
        if (systemResource != null) {
            JSONArray jsonArray = new JSONArray(systemResource.getContent());
            List<String> resourceCodeList = getCodeListByUserId(userId);
            getUserResourceList(jsonArray, resourceCodeList, list, typeList);
        }
        return list;
    }

    private void getUserResourceList(JSONArray jsonArray, List<String> resourceCodeList, JSONArray list, List<ResourceTypeEnum> typeList) {
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            String code = jsonObject.getStr("code");
            Integer type = jsonObject.getInt("type");
            if ((resourceCodeList != null && resourceCodeList.contains(code)) && typeList.contains(ResourceTypeEnum.getById(type))) {
                JSONObject copyJsonObject = new JSONObject();
                copyJsonObject.putAll(jsonObject);
                copyJsonObject.remove("children");
                list.add(copyJsonObject);
            }
            JSONArray children = jsonObject.getJSONArray("children");
            if (children != null) {
                getUserResourceList(children, resourceCodeList, list, typeList);
            }
        }
    }
    @Override
    public List<String> getCodeListByUserId(Long userId) {
        List<Role> userRoleList = roleRepository.getRoleListByUserId(userId);
        HashSet<String> resourceCodeSet = new HashSet<>();
        for (Role role : userRoleList) {
            if (Boolean.TRUE == role.getIsAdmin()) {
                return null;
            }
            List<String> resourceCodeList = JSONUtil.toList(role.getResourceCodeList(), String.class);
            resourceCodeSet.addAll(resourceCodeList);
        }
        return new ArrayList<>(resourceCodeSet);
    }

    @Override
    public GetResourceTreeVo getAuthorizedTree(GetResourceTreeParam param) {
        GetResourceTreeVo vo = new GetResourceTreeVo();
        List<String> resourceCodeList=new ArrayList<>();
        JSONArray list =getResourceTree(ResourceTypeEnum.getList());

        if(param.getRoleId()!=null){
            Role role = roleRepository.getByIdCheck(param.getRoleId());
            if (role.getResourceCodeList() == null) {
                resourceCodeList = new ArrayList<>();
            } else {
                resourceCodeList = JSONUtil.toList(role.getResourceCodeList(), String.class);
            }
        }

        vo.setResourceCodeList(resourceCodeList);
        vo.setList(list);
        return vo;
    }


    /**
     * 过滤资源树 null为获取全部资源
     */
    private void filterResourceTree(JSONArray jsonArray, List<String> resourceCodeList, List<ResourceTypeEnum> typeList) {
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            String code = jsonObject.getStr("code");
            Integer type = jsonObject.getInt("type");
            if ((resourceCodeList != null && !resourceCodeList.contains(code)) || !typeList.contains(ResourceTypeEnum.getById(type))) {
                jsonArray.remove(i);
                i--;
                continue;
            }
            JSONArray children = jsonObject.getJSONArray("children");
            if (children != null) {
                filterResourceTree(children, resourceCodeList, typeList);
            }
        }
    }

    /**
     * 校验资源
     */
    private void checkResource(JSONArray param, List<String> codeList) {
        for (int i = 0; i < param.size(); i++) {
            JSONObject jsonObject = param.getJSONObject(i);
            String code = jsonObject.getStr("code");
            if (code == null) {
                throw new BizException("资源编号不能为空");
            }
            if (codeList.contains(code)) {
                throw new BizException("资源编号重复");
            }
            codeList.add(code);
            Integer type = jsonObject.getInt("type");
            if (type == null) {
                throw new BizException("资源类型不能为空");
            }
            if (ResourceTypeEnum.getById(type) == null) {
                throw new BizException("资源类型不存在");
            }
            String name = jsonObject.getStr("name");
            if (name == null) {
                throw new BizException("资源名称不能为空");
            }
            JSONArray children = jsonObject.getJSONArray("children");
            if (children != null) {
                checkResource(children, codeList);
            }
        }
    }
}



